package model

import (
	"KumquatDrivesServices/enums"
	"KumquatDrivesServices/global"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/go-redis/redis"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
	"time"
)

type UserModel struct {
	Model
	UserEmail          string `json:"userEmail" gorm:"size:256;uniqueIndex;comment:用户名;"`
	Password           string `json:"-" gorm:"size:64;comment:密码;"`
	NickName           string `json:"nickName" gorm:"size:36;comment:昵称;"`
	UserAvatar         string `json:"userAvatar" gorm:"size:255;comment:头像;"`
	TotalCapacity      int64  `json:"totalCapacity" gorm:"comment:总容量;"`
	CapacityUsed       int64  `json:"capacityUsed" gorm:"comment:已用容量;"`
	TimeOfRegistration int64  `json:"timeOfRegistration" gorm:"comment:注册时间;"`
}

type CapacityModel struct {
	UserEmail     string `json:"userEmail"`
	TotalCapacity int64  `json:"totalCapacity"`
	CapacityUsed  int64  `json:"capacityUsed"`
}

// getUserCapacityFromDB 从数据库获取用户容量
func (u *UserModel) getUserCapacityFromDB() (*CapacityModel, error) {
	var userModel UserModel
	if err := global.DB.Where("id = ?", u.ID).First(&userModel).Error; err != nil {
		return nil, err
	}
	capacity := &CapacityModel{
		UserEmail:     userModel.UserEmail,
		TotalCapacity: userModel.TotalCapacity,
		CapacityUsed:  userModel.CapacityUsed,
	}
	// 更新缓存
	if err := userModel.CacheUserInfo(); err != nil {
		logrus.Warnf("更新用户容量缓存失败:%v", err)
	}
	return capacity, nil
}

// GetCacheUserInfo 获取缓存用户信息
func (u *UserModel) GetCacheUserInfo() (*CapacityModel, error) {
	key := fmt.Sprintf("userModel:%d", u.ID)
	redisRes, redisErr := global.Redis.Get(key).Result()
	if redisErr != nil {
		if errors.Is(redisErr, redis.Nil) {
			return u.getUserCapacityFromDB()
		}
		logrus.Errorf("获取用户容量缓存失败:%v", redisErr)
		return nil, redisErr
	}
	capacity := &CapacityModel{}
	if jsonErr := json.Unmarshal([]byte(redisRes), capacity); jsonErr != nil {
		return nil, jsonErr
	}
	return capacity, nil
}

// CacheUserInfo 缓存用户信息
func (u *UserModel) CacheUserInfo() error {
	key := fmt.Sprintf("userModel:%d", u.ID)
	capacity := CapacityModel{
		UserEmail:     u.UserEmail,
		TotalCapacity: u.TotalCapacity,
		CapacityUsed:  u.CapacityUsed,
	}
	CapacityJson, JsonErr := json.Marshal(capacity)
	if JsonErr != nil {
		return fmt.Errorf("json序列失败：%v", JsonErr)
	}
	if err := global.Redis.Set(key, CapacityJson, time.Duration(global.Config.Jwt.RefreshExp)*time.Hour).Err(); err != nil {
		logrus.Errorf("用户容量缓存失败:%v", err)
		return err
	}
	return nil
}

// DeleteCacheUser 删除缓存
func (u *UserModel) DeleteCacheUser() error {
	key := fmt.Sprintf("userModel:%d", u.ID)
	if err := global.Redis.Del(key).Err(); err != nil {
		return err
	}
	return nil
}

// GetUserRemainingCapacity 获取用户剩余容量
func (u *UserModel) GetUserRemainingCapacity() (int64, error) {
	capacity, err := u.GetCacheUserInfo()
	if err != nil {
		return 0, err
	}
	return capacity.TotalCapacity - capacity.CapacityUsed, nil
}

// GetTotalCapacityAndCapacityUsed 获取用户总容量和已用容量
func (u *UserModel) GetTotalCapacityAndCapacityUsed() (TotalCapacity int64, CapacityUsed int64, err error) {
	capacity, err := u.GetCacheUserInfo()
	if err != nil {
		return 0, 0, err
	}
	return capacity.TotalCapacity, capacity.CapacityUsed, nil
}

// UpdateUserCapacity 更新用户容量
func (u *UserModel) UpdateUserCapacity(size int64, tag enums.UserCapacity) error {
	var userModel UserModel
	if err := global.DB.Where("id = ?", u.ID).First(&userModel).Error; err != nil {
		return err
	}
	if userModel.CapacityUsed+size > userModel.TotalCapacity {
		return fmt.Errorf("更新容量超限")
	}
	capacityUsedAdd := gorm.Expr("capacity_used+?", size)
	if tag {
		capacityUsedAdd = gorm.Expr("capacity_used-?", size)
	}
	var userModel2 UserModel
	dbTransaction := global.DB.Begin()

	if err := dbTransaction.Model(&userModel2).Where("id = ?", u.ID).
		Update("capacity_used", capacityUsedAdd).Error; err != nil {
		dbTransaction.Rollback()
		return err
	}
	if err := dbTransaction.Commit().Error; err != nil {
		dbTransaction.Rollback()
		return err
	}
	if err := u.DeleteCacheUser(); err != nil {
		logrus.Warnf("删除缓存失败:%v", err)
	}
	if err := userModel2.CacheUserInfo(); err != nil {
		logrus.Warnf("设置缓存失败:%v", err)
	}
	return nil
}
